package org.googlecode.viewt.core.tools.web;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.Reader;

import org.apache.commons.cli.CommandLine;
import org.apache.commons.cli.CommandLineParser;
import org.apache.commons.cli.GnuParser;
import org.apache.commons.cli.OptionBuilder;
import org.apache.commons.cli.Options;
import org.apache.commons.cli.ParseException;
import org.exolab.castor.xml.MarshalException;
import org.exolab.castor.xml.ValidationException;
import org.googlecode.viewt.core.tools.formbean.FormBeanCfgRepository;
import org.googlecode.viewt.core.tools.web.types.Actions;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class WebGenerateCommand {
	private final static Logger logger = LoggerFactory
			.getLogger(WebGenerateCommand.class);
	public static final String OPT_ACTION_FILE = "i";
	public static final String OPT_DEPCFG_FORMBEAN = "formbeans";
	public static final String OPT_BLSRC_PATH = "blpath";
	public static final String OPT_IMP_DEST = "imp";
	public static final String OPT_CFG_DEST = "cfg";
	public static final String OPT_PREFIX_PACKAGE = "prepack";
	public static final String OPT_COPYRIGHT = "copyright";
	public static final String OPT_AUTHOR = "author";
	private Actions actionsDef = null;

	private String actionFile = null;

	private FormBeanCfgRepository formbeanRepository = new FormBeanCfgRepository();

	private String[] formbeanCfgs = null;

	private String[] blPaths = null;

	private String impDestPath = null;

	private String cfgDestPath = null;

	private String prePackName = "com.leadron";

	private String copyright = null;

	private String author = null;

	public void parseArgs(String[] args) throws ParseException {
		CommandLineParser parser = new GnuParser();
		OptionBuilder.hasArg();
		OptionBuilder.isRequired();
		OptionBuilder
				.withDescription("web action config file by which to generate");
		OptionBuilder.hasArg();
		OptionBuilder.hasArgs();
		OptionBuilder.withDescription("dependent formbean config files");
		OptionBuilder.hasArg();
		OptionBuilder.hasArgs();
		OptionBuilder.isRequired();
		OptionBuilder.withDescription("business logic source path");
		OptionBuilder.hasArg();
		OptionBuilder.isRequired();
		OptionBuilder
				.withDescription("path to output implementation class file");
		OptionBuilder.hasArg();
		OptionBuilder.isRequired();
		OptionBuilder.withDescription("path to output config file");
		OptionBuilder.hasArg();
		OptionBuilder.withDescription("package prefix of generated class");
		OptionBuilder.hasArg();
		OptionBuilder
				.withDescription("copyright information for generated code");
		OptionBuilder.hasArg();
		OptionBuilder.withDescription("author information for generated code");
		Options options = new Options().addOption(OptionBuilder.create("i"))
				.addOption(OptionBuilder.create("formbeans")).addOption(
						OptionBuilder.create("blpath")).addOption(
						OptionBuilder.create("imp")).addOption(
						OptionBuilder.create("cfg")).addOption(
						OptionBuilder.create("prepack")).addOption(
						OptionBuilder.create("copyright")).addOption(
						OptionBuilder.create("author"));

		CommandLine cmdLine = parser.parse(options, args);

		this.actionFile = cmdLine.getOptionValue("i");
		this.formbeanCfgs = cmdLine.getOptionValues("formbeans");
		this.blPaths = cmdLine.getOptionValues("blpath");
		this.impDestPath = cmdLine.getOptionValue("imp");
		this.cfgDestPath = cmdLine.getOptionValue("cfg");
		if (cmdLine.hasOption("prepack"))
			this.prePackName = cmdLine.getOptionValue("prepack");
		if (cmdLine.hasOption("copyright"))
			this.copyright = cmdLine.getOptionValue("copyright");
		if (cmdLine.hasOption("author")) {
			this.author = cmdLine.getOptionValue("author");
		}

		System.out.println("Web action config file:\t\t" + this.actionFile);
		if (this.formbeanCfgs != null) {
			System.out.println("Dependent formbean config file:");
			for (int i = 0; i < this.formbeanCfgs.length; ++i)
				System.out.println("\t" + this.formbeanCfgs[i]);
		}
		System.out.println("Business logic source path:");
		for (int i = 0; i < this.blPaths.length; ++i)
			System.out.println("\t" + this.blPaths[i]);
		System.out.println("Implement output path:\t" + this.impDestPath);
		System.out.println("Config output path:\t" + this.cfgDestPath);
		System.out.println("Package prefix:\t" + this.prePackName);
	}

	public void loadConfig() {
		logger.debug("Begin to load web action configuration from file:"
				+ this.actionFile);
		try {
			Reader reader = new InputStreamReader(new FileInputStream(
					this.actionFile));
			this.actionsDef = Actions.unmarshal(reader);
			reader.close();

			int len = (this.formbeanCfgs == null) ? 0
					: this.formbeanCfgs.length;
			if (len > 0) {
				this.formbeanRepository.setMainDef(this.formbeanCfgs[0],
						this.prePackName);
				for (int i = 1; i < len; ++i)
					this.formbeanRepository
							.addFormBeanConfig(this.formbeanCfgs[i]);
			}
		} catch (FileNotFoundException fnfEx) {
			logger.error("Specified action config file:" + this.actionFile
					+ " not found, can not load config");
		} catch (IOException ioEx) {
			logger.error("Error when reading from file:" + this.actionFile
					+ ", can not load config");
		} catch (MarshalException marshalEx) {
			logger.error("Marshal action config from file:" + this.actionFile
					+ " error, can not load config");
		} catch (ValidationException validateEx) {
			logger.error("Validate action config:" + this.actionFile
					+ " fail, can not load config");
		}

		logger.debug("Load web action configuration succeed");
	}

	public void performGen() throws Exception {
		BaseWebGenerator generator = null;

		logger.debug("Begin to generate web action implement file");
		generator = new WebActionImplGenerator();
		generator.setFormbeanRepository(this.formbeanRepository);
		generator.setBLPath(this.blPaths);
		generator.setPrePackName(this.prePackName);
		generator.setCopyright(this.copyright);
		generator.setAuthor(this.author);
		generator.init(this.actionsDef, this.impDestPath);
		generator.performGen();
		logger.debug("End generate web action implement file");

		logger.debug("Begin to generate spring bean config");
		generator = new BeanConfigGenerator();
		generator.setFormbeanRepository(this.formbeanRepository);
		generator.setBLPath(this.blPaths);
		generator.setPrePackName(this.prePackName);
		generator.setCopyright(this.copyright);
		generator.setAuthor(this.author);
		generator.init(this.actionsDef, this.cfgDestPath);
		generator.performGen();
		logger.debug("End generate spring bean config");

		logger.debug("Begin to generate webwork config");
		generator = new WebWorkConfigGenerator();
		generator.setFormbeanRepository(this.formbeanRepository);
		generator.setBLPath(this.blPaths);
		generator.setPrePackName(this.prePackName);
		generator.setCopyright(this.copyright);
		generator.setAuthor(this.author);
		generator.init(this.actionsDef, this.cfgDestPath);
		generator.performGen();
		logger.debug("End generate webwork config");

		logger.debug("Begin to generate validation config");
		generator = new ValidationConfigGenerator();
		generator.setFormbeanRepository(this.formbeanRepository);
		generator.setBLPath(this.blPaths);
		generator.setPrePackName(this.prePackName);
		generator.setCopyright(this.copyright);
		generator.setAuthor(this.author);
		generator.init(this.actionsDef, this.cfgDestPath);
		generator.performGen();
		logger.debug("End generate validation config");

		logger.debug("Begin to generate action-formbean relation config");
		generator = new ActionBeanRelationGenerator();
		generator.setFormbeanRepository(this.formbeanRepository);
		generator.setBLPath(this.blPaths);
		generator.setPrePackName(this.prePackName);
		generator.setCopyright(this.copyright);
		generator.setAuthor(this.author);
		generator.init(this.actionsDef, this.cfgDestPath);
		generator.performGen();
		logger.debug("End generate action-formbean relation config");
	}

	public static void main(String[] args) {
		System.out
				.println("Web action generator, Copyright (c) 2006-2008 Leadron Information Technoloy co.,Ltd.");
		try {
			WebGenerateCommand command = new WebGenerateCommand();
			command.parseArgs(args);
			command.loadConfig();
			command.performGen();
		} catch (ParseException parseEx) {
			System.out.println("Invalid command line argument, check the doc");
			System.out.println(parseEx.getMessage());
			System.exit(-1);
		} catch (Exception ex) {
			System.out.println("Generate web action source file fail");
			ex.printStackTrace();
			System.exit(-1);
		}

		System.out.println("Generation done.");
	}
}